home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 August: Tool Chest / Apple_Developer_Group_August_1996_Tool_Chest.iso / Sample Code / Snippets / Files / SFGetFolder C / main.c next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  8.1 KB  |  368 lines  |  [TEXT/KAHL]

  1. /*    StandardGetFolder example
  2.  
  3.     Steve Falkenburg -- MacDTS
  4.     
  5.     This sample uses the new System 7 CustomGetFile routine
  6.     to provide a StandardGetFolder call to be used by applications
  7.     when the user needs to select a folder instead of a file.
  8.     
  9.     It's written in Think C, but should work in MPW if a few #include
  10.     files are added.
  11.     
  12.     The style of the dialog box is taken from the Human Interface note
  13.     on folder selection.
  14.     
  15.     SJF        5/2/92        added check for empty filename and call to MakeFSSpec
  16.     SJF        5/2/92        added check for refcon in filter and hook routines
  17.     SJF        10/30/91    original coding
  18.     
  19. */
  20.  
  21. #include <string.h>
  22. #include <GestaltEqu.h>
  23. #include <Folders.h>
  24. #include <Traps.h>
  25. #include <Script.h>
  26. #include <Aliases.h>
  27. #include "trapavail.h"
  28.  
  29. /* prototypes */
  30.  
  31. void InitStuff(void);
  32. Boolean CustomGet(FSSpec *fSpec);
  33. pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData);
  34. pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData);
  35. void HitButton(DialogPtr theDlg,short item);
  36. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr);
  37. void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg);
  38. Boolean SameFile(FSSpec *file1,FSSpec *file2);
  39. Boolean GetFSSpecPartialName(FSSpec *file,StringPtr fName);
  40. OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum);
  41. OSErr MakeCanonFSSpec(FSSpec *fSpec);
  42. Boolean ShouldHiliteSelect(FSSpec *fSpec);
  43.  
  44. /* typedefs */
  45.  
  46. typedef struct {
  47.     StandardFileReply *replyPtr;
  48.     FSSpec oldSelection;
  49. } SFData, *SFDataPtr;
  50.  
  51. /* constants */
  52.  
  53. #define    kSelectItem            10
  54. #define    kSFDlg                128
  55. #define    kCanSelectDesktop    true
  56. #define    kSelectStrRsrc        128
  57. #define kDefaultSelectString "\pSelect"
  58. #define    kDeskStrRsrc        129
  59. #define    kDefaultDeskString    "\pDesktop"
  60. #define    kSelectKey            's'
  61.  
  62. /* globals */
  63.  
  64. Boolean gHasFindFolder;
  65. FSSpec gDeskFolderSpec;
  66. Str255 gSelectString;
  67. Str255 gDesktopFName;
  68.  
  69. void main(void)
  70. {
  71.     FSSpec fSpec;
  72.     Boolean good;
  73.     
  74.     InitStuff();
  75.     
  76.     good = CustomGet(&fSpec);
  77. }
  78.  
  79.  
  80. /* initialize managers */
  81.  
  82. void InitStuff(void)
  83. {
  84.     OSErr err;
  85.     long gResponse;
  86.     Handle strHndl;
  87.     
  88.     MaxApplZone();
  89.     MoreMasters();
  90.     MoreMasters();
  91.     
  92.     InitGraf(&qd.thePort);
  93.     InitFonts();
  94.     InitWindows();
  95.     InitMenus();
  96.     TEInit();
  97.     InitDialogs(nil);
  98.     FlushEvents(everyEvent,0);
  99.     InitCursor();
  100.     
  101.     gHasFindFolder = false;
  102.     if (TrapAvailable(_GestaltDispatch)) {
  103.         err = Gestalt(gestaltFindFolderAttr,&gResponse);
  104.         if (err==noErr)
  105.             gHasFindFolder = (gResponse && (1<<gestaltFindFolderPresent));
  106.     }
  107.     
  108.     strHndl = Get1Resource('STR ',kSelectStrRsrc);
  109.     if (ResError()!=noErr || !strHndl || !*strHndl)
  110.         BlockMove(kDefaultSelectString,gSelectString,kDefaultSelectString[0]+1);
  111.     else {
  112.         BlockMove(*strHndl,&gSelectString,(long)((unsigned char *)(*strHndl)[0]+1));
  113.         ReleaseResource(strHndl);
  114.     }
  115.  
  116.     strHndl = Get1Resource('STR ',kDeskStrRsrc);
  117.     if (ResError()!=noErr || !strHndl || !*strHndl)
  118.         BlockMove(kDefaultDeskString,gDesktopFName,kDefaultSelectString[0]+1);
  119.     else {
  120.         BlockMove(*strHndl,&gDesktopFName,(long)((unsigned char *)(*strHndl)[0]+1));
  121.         ReleaseResource(strHndl);
  122.     }
  123. }
  124.  
  125.  
  126. /* do getfile */
  127.  
  128. Boolean CustomGet(FSSpec *fSpec)
  129. {
  130.     Point where = {-1,-1};
  131.     SFReply reply;
  132.     DialogPtr theDialog;
  133.     short item;
  134.     StandardFileReply sfReply;
  135.     SFData sfUserData;
  136.     OSErr err;
  137.     Boolean targetIsFolder,wasAliased;
  138.     
  139.     /* initialize user data area */
  140.     
  141.     sfUserData.replyPtr = &sfReply;
  142.     sfUserData.oldSelection.vRefNum = -9999;    /* init to ridiculous value */
  143.     
  144.     CustomGetFile(FilterAllFiles,-1,nil,&sfReply,kSFDlg,where,MyDlgHook,
  145.                     MyModalFilter,nil,nil,&sfUserData);
  146.     
  147.     if (sfReply.sfGood) {
  148.         err = ResolveAliasFile(&sfReply.sfFile,true,&targetIsFolder,&wasAliased);
  149.         if (err!=noErr)
  150.             return false;
  151.     }
  152.     
  153.     err = FSMakeFSSpec(sfReply.sfFile.vRefNum,sfReply.sfFile.parID,sfReply.sfFile.name,fSpec);
  154.     if (err!=noErr)
  155.         return false;
  156.     
  157.     return sfReply.sfGood;
  158. }
  159.  
  160.  
  161. /*    this dialog hook checks the contents of the additional edit fields
  162.     when the user selects a file.  The focus of the dialog is changed if one
  163.     of the fields is out of range.
  164. */
  165.  
  166. pascal short MyDlgHook(short item,DialogPtr theDlg,Ptr userData)
  167. {
  168.     SFDataPtr sfUserData;
  169.     Boolean hiliteButton;
  170.     FSSpec curSpec;
  171.     OSType refCon;
  172.     
  173.     refCon = GetWRefCon(theDlg);
  174.     if (refCon!=sfMainDialogRefCon)
  175.         return item;
  176.         
  177.     sfUserData = (SFDataPtr) userData;
  178.     
  179.     if (item==sfHookFirstCall || item==sfHookLastCall)
  180.         return item;
  181.     
  182.     if (item==sfItemVolumeUser) {
  183.         sfUserData->replyPtr->sfFile.name[0] = '\0';
  184.         sfUserData->replyPtr->sfFile.parID = 2;
  185.         sfUserData->replyPtr->sfIsFolder = false;
  186.         sfUserData->replyPtr->sfIsVolume = false;
  187.         sfUserData->replyPtr->sfFlags = 0;
  188.         item = sfHookChangeSelection;
  189.     }
  190.         
  191.     if (!SameFile(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection)) {
  192.         BlockMove(&sfUserData->replyPtr->sfFile,&curSpec,sizeof(FSSpec));
  193.         MakeCanonFSSpec(&curSpec);
  194.         
  195.         if (curSpec.vRefNum!=sfUserData->oldSelection.vRefNum)
  196.             GetDeskFolderSpec(&gDeskFolderSpec,curSpec.vRefNum);    
  197.         SetSelectButtonName(curSpec.name,ShouldHiliteSelect(&curSpec),theDlg);
  198.         
  199.         BlockMove(&sfUserData->replyPtr->sfFile,&sfUserData->oldSelection,sizeof(FSSpec));
  200.     }
  201.     
  202.     if (item==kSelectItem)
  203.         item = sfItemOpenButton;
  204.         
  205.     return item;
  206. }
  207.  
  208.  
  209. pascal Boolean MyModalFilter(DialogPtr theDlg,EventRecord *ev,short *itemHit,Ptr myData)
  210. {
  211.     Boolean evHandled;
  212.     char keyPressed;
  213.     OSType refCon;
  214.     
  215.     refCon = GetWRefCon(theDlg);
  216.     if (refCon!=sfMainDialogRefCon)
  217.         return false;
  218.         
  219.     evHandled = false;
  220.     
  221.     switch (ev->what) {
  222.         case keyDown:
  223.         case autoKey:
  224.             keyPressed = ev->message & charCodeMask;
  225.             if ((ev->modifiers & cmdKey) != 0) {
  226.                 switch (keyPressed) {
  227.                     case kSelectKey:
  228.                         HitButton(theDlg,kSelectItem);
  229.                         *itemHit = kSelectItem;
  230.                         evHandled = true;
  231.                         break;
  232.                 }
  233.             }
  234.             break;
  235.     }
  236.     
  237.     return evHandled;
  238. }
  239.  
  240.  
  241. void HitButton(DialogPtr theDlg,short item)
  242. {
  243.     short iType;
  244.     ControlHandle iHndl;
  245.     Rect iRect;
  246.     long fTicks;
  247.     
  248.     GetDItem(theDlg,item,&iType,&iHndl,&iRect);
  249.     HiliteControl(iHndl,inButton);
  250.     Delay(5,&fTicks);
  251.     HiliteControl(iHndl,0);
  252. }
  253.  
  254.  
  255. pascal Boolean FilterAllFiles(CInfoPBPtr pb, Ptr myDataPtr)
  256. {
  257.     if (pb->hFileInfo.ioFlAttrib & (1<<4))    /* file is a directory */
  258.         return false;
  259.  
  260.     return true;
  261. }
  262.  
  263.  
  264. void SetSelectButtonName(StringPtr selName,Boolean hilited,DialogPtr theDlg)
  265. {
  266.     ControlHandle selectButton;
  267.     short iType;
  268.     Handle iHndl;
  269.     Rect iRect;
  270.     Str255 storeName,tempLenStr,tempSelName;
  271.     short btnWidth;
  272.     
  273.     BlockMove(selName,tempSelName,selName[0]+1);
  274.     GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
  275.     
  276.     /* truncate select name to fit in button */
  277.     
  278.     btnWidth = iRect.right - iRect.left;
  279.     BlockMove(gSelectString,tempLenStr,gSelectString[0]+1);
  280.     p2cstr(tempLenStr);
  281.     strcat((char *)tempLenStr," “”  ");
  282.     c2pstr((char *)tempLenStr);
  283.     btnWidth -= StringWidth(tempLenStr);
  284.     TruncString(btnWidth,tempSelName,smTruncMiddle);
  285.     
  286.     BlockMove(gSelectString,storeName,gSelectString[0]+1);
  287.     p2cstr(storeName);
  288.     p2cstr(tempSelName);
  289.     strcat((char *)storeName," “");
  290.     strcat((char *)storeName,(char *)tempSelName);
  291.     strcat((char *)storeName,"”");
  292.     
  293.     c2pstr((char *)storeName);
  294.     c2pstr(tempSelName);
  295.     SetCTitle(iHndl,storeName);
  296.     
  297.     SetDItem(theDlg,kSelectItem,iType,iHndl,&iRect);
  298.  
  299.     if (hilited)
  300.         HiliteControl(iHndl,0);
  301.     else
  302.         HiliteControl(iHndl,255);        
  303. }
  304.  
  305.  
  306. Boolean SameFile(FSSpec *file1,FSSpec *file2)
  307. {
  308.     if (file1->vRefNum != file2->vRefNum)
  309.         return false;
  310.     if (file1->parID != file2->parID)
  311.         return false;
  312.     if (!EqualString(file1->name,file2->name,false,true))
  313.         return false;
  314.     
  315.     return true;
  316. }
  317.  
  318.  
  319. OSErr GetDeskFolderSpec(FSSpec *fSpec,short vRefNum)
  320. {
  321.     DirInfo infoPB;
  322.     OSErr err;
  323.     
  324.     if (!gHasFindFolder) {
  325.         fSpec->vRefNum = -9999;
  326.         return -1;
  327.     }
  328.     
  329.     fSpec->name[0] = '\0';
  330.     err = FindFolder(vRefNum,kDesktopFolderType,kDontCreateFolder,
  331.                         &fSpec->vRefNum,&fSpec->parID);
  332.     if (err!=noErr)
  333.         return err;
  334.     
  335.     return MakeCanonFSSpec(fSpec);
  336. }
  337.  
  338.  
  339. Boolean ShouldHiliteSelect(FSSpec *fSpec)
  340. {
  341.     if (SameFile(fSpec,&gDeskFolderSpec)) {
  342.         BlockMove(gDesktopFName,fSpec->name,gDesktopFName[0]+1);
  343.         return kCanSelectDesktop;
  344.     }
  345.     else
  346.         return true;
  347. }
  348.  
  349.  
  350. OSErr MakeCanonFSSpec(FSSpec *fSpec)
  351. {
  352.     DirInfo infoPB;
  353.     OSErr err;
  354.  
  355.     if (fSpec->name[0] != '\0')
  356.         return;
  357.         
  358.     infoPB.ioNamePtr = fSpec->name;
  359.     infoPB.ioVRefNum = fSpec->vRefNum;
  360.     infoPB.ioDrDirID = fSpec->parID;
  361.     infoPB.ioFDirIndex = -1;
  362.     err = PBGetCatInfo(&infoPB,false);
  363.     fSpec->parID = infoPB.ioDrParID;
  364.     
  365.     return err;
  366. }
  367.  
  368.